package io.github.topcatv.mall.model.sys.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import io.github.topcatv.mall.common.ao.*;
import io.github.topcatv.mall.common.security.jwt.JwtTokenUtil;
import io.github.topcatv.mall.common.support.JsonArg;
import io.github.topcatv.mall.friends.FriendsClient;
import io.github.topcatv.mall.model.sys.entity.Permission;
import io.github.topcatv.mall.model.sys.entity.Role;
import io.github.topcatv.mall.model.sys.entity.User;
import io.github.topcatv.mall.model.sys.service.IPermissionService;
import io.github.topcatv.mall.model.sys.service.IRoleService;
import io.github.topcatv.mall.model.sys.service.IUserService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Comparator.comparing;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author liuyi
 * @since 2019-10-14
 */
@Api(value = "用户API")
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private IUserService userService;

    @Resource
    private IPermissionService permissionService;

    @Resource
    private IRoleService roleService;

    @Resource
    private PasswordEncoder passwordEncoder;

    @PostMapping("/addRoles")
    public ReturnObject addRoles(@JsonArg Integer id, @JsonArg Integer[] roleIds) {
        userService.addRoles(id, roleIds);
        return ReturnObject.success();
    }

    @PutMapping("/changeStatus")
    public ReturnObject changeStatus(@JsonArg Integer id, @JsonArg Boolean lock) {
        UserAo userAo = new UserAo();
        userAo.setId(id);
        userAo.setLocked(lock);
        return userService.updateById(userAo.toEntity()) ? ReturnObject.success() : ReturnObject.error("锁定状态修改失败");
    }

    @DeleteMapping("/{userId}")
    public ReturnObject removeUser(@PathVariable("userId") Integer userId) {
        return userService.removeById(userId) ? ReturnObject.success() : ReturnObject.error("删除失败");
    }

    @PostMapping
    public ReturnObject updateUser(@RequestBody UserAo user) {
        User entity = user.toEntity();
        if (StringUtils.isNotBlank(entity.getPwd())) {
            if (StringUtils.isNotBlank(user.getOriginPwd())) {
                QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(User::getId, user.getId())
                        .eq(User::getPwd, passwordEncoder.encode(user.getOriginPwd()));
                if (userService.count(queryWrapper) <= 0) {
                    return ReturnObject.error("旧密码不正确");
                }
            }
            entity.setPwd(passwordEncoder.encode(entity.getPwd()));
        } else {
            entity.setPwd(null);
        }
        return userService.updateById(entity) ? ReturnObject.success() : ReturnObject.error("更新失败");
    }

    @GetMapping("")
    public ReturnObject queryUser(String keyword, long pageNo, long pageSize) {
        QueryWrapper<User> query = new QueryWrapper<>();
        if (StringUtils.isNotBlank(keyword)) {
            query.lambda().like(User::getUsername, keyword).or().like(User::getMobile, keyword);
        }
        IPage<User> page = userService.page(new Page<>(pageNo, pageSize), query);
        return ReturnObject.success().put("users", page);
    }

    @GetMapping("/{id}")
    public ReturnObject fetch(@PathVariable("id") Integer id) {
        User user = userService.getById(id);
        UserAo userAo = buildUser(user);
        return userAo == null ? ReturnObject.error("找不到用户") : ReturnObject.success().put("user", userAo);
    }

    private UserAo buildUser(User user) {
        if (user == null) {
            return null;
        }

        UserAo target = new UserAo(user);
        Set<Permission> permissions = permissionService.selectByUserId(user.getId());
        Set<Role> roles = roleService.selectByUserId(user.getId());
        target.setMenus(buildMenu(permissions));
        target.setPermissions(buildPermissions(permissions));
        target.setRoles(buildRoles(roles));

        return target;
    }

    @Resource
    private FriendsClient friendsClient;

    @GetMapping("/info")
    public ReturnObject userInfo(String token) {
        System.out.println(friendsClient.hello("liuyi"));
        String username = jwtTokenUtil.getUsernameFromToken(token);
        QueryWrapper<User> query = new QueryWrapper<>();
        query.lambda().eq(User::getUsername, username);
        UserAo userAo = buildUser(userService.getOne(query));

        return userAo == null ? ReturnObject.error("找不到用户") : ReturnObject.success().put("user", userAo);
    }

    private List<RoleAo> buildRoles(Set<Role> roles) {
        if (roles.isEmpty()) {
            return Lists.newArrayList();
        }
        return roles.stream()
                .map(RoleAo::new)
                .collect(Collectors.toList());
    }

    private List<PermissionAo> buildPermissions(Set<Permission> permissions) {
        if (permissions.isEmpty()) {
            return Lists.newArrayList();
        }
        return permissions.stream()
                .filter(p -> p.getType() == Permission.TYPE_ACTION)
                .sorted(comparing(Permission::getSortOrder))
                .map(PermissionAo::new)
                .collect(Collectors.toList());
    }

    private List<MenuAo> buildMenu(Set<Permission> permissions) {
        MenuAo root = new MenuAo();
        root.setLevel(0);
        root.setTitle("root");
        root.setName("root");
        fetchChildren(root, permissions);
        return root.getChildren();
    }

    private void fetchChildren(MenuAo root, Set<Permission> permissions) {
        if (permissions.isEmpty()) {
            return;
        }
        // 找到下一级菜单
        List<MenuAo> children = permissions.stream()
                // 类型是菜单
                .filter(p -> Objects.equals(p.getParentId(), root.getId()) && p.getType() == Permission.TYPE_MENU)
                .sorted(comparing(Permission::getSortOrder))
                .map(MenuAo::new)
                .collect(Collectors.toList());
        root.setChildren(children);
        // 过滤掉已处理的子菜单,把未处理的子菜单找出来
        List<Integer> ids = children.stream().map(MenuAo::getId).collect(Collectors.toList());
        Set<Permission> ps = permissions.stream().filter(p -> !ids.contains(p.getId())).collect(Collectors.toSet());
        // 继续找自己的子菜单
        children.forEach(element -> fetchChildren(element, ps));
    }

}
